/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import common.GeneralHandling;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import pojo.Tag;
import org.apache.cassandra.thrift.*;
import org.apache.thrift.TException;
/**
 *
 * @author tipuder
 */
public class TagDAO {
    private static Cassandra.Client client;
    private static TagDAO instance;
    
    public static TagDAO getInstance(Cassandra.Client _client)
    {
        if (instance != null)
            return instance;
        instance = new TagDAO();
        client = _client;
        return instance;
    }
    
    public boolean InsertTag(Tag newTag)
    {
        boolean result = false;
        try {
                
                //Tạo supercolumn list_status_ID
//                SuperColumn liststatus = new SuperColumn();
//                liststatus.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus);
//                List<String> lstatus = newTag.getList_status_ID();
//                for (int i = 0; i < newTag.getList_status_ID().size(); i++)
//                {
//                    String colname = lstatus.get(i);
//                    liststatus.addToColumns(common.GeneralHandling.createCol(colname, ""));
//                }
                
                //Tạo supercolumn info_tag
                SuperColumn info_tag = new SuperColumn();
                info_tag.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_info);
                //String createD = Long.toString((new Date()).getTime());
                
                info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_cdate, ""));
                
                String modifyD = "";
                info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_mdate, modifyD));
                
                String state = "public";
                info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_state, state));
                
                //Insert supercolunm bằng batch_mutate
                ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(newTag.getName_tag());
                
                List<Mutation> mutations = new ArrayList<Mutation>();
                
                ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
                Mutation m = new Mutation();
                
                colorsupcol.setSuper_column(info_tag);
                m.setColumn_or_supercolumn(colorsupcol);
                mutations.add(m);
                
//                colorsupcol = new ColumnOrSuperColumn();
//                m = new Mutation();
//                colorsupcol.setSuper_column(liststatus);
//                m.setColumn_or_supercolumn(colorsupcol);
//                mutations.add(m);
                
                Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
                keyMutations.put(Tag.col_parent, mutations);
                
                Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
                mutationsMap.put(rowkey, keyMutations);
                client.batch_mutate(mutationsMap, common.Constants.CL);
                result = true;
        
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        return result;
    }
    
    public boolean InsertStatusIDtoTag(String StatusID,String nameTag)
    {
        boolean result = false;
        try {
            
            Tag updateTag = selectTagFromID(nameTag);
            SuperColumn liststatus = new SuperColumn();
            liststatus.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus);
            
            List<String> lstatus = updateTag.getList_status_ID();
            if (lstatus == null)
                lstatus = new ArrayList<String>();
            lstatus.add(StatusID);
            for (int i = 0; i < lstatus.size(); i++)
            {
                String colname = lstatus.get(i);
                liststatus.addToColumns(common.GeneralHandling.createCol(colname, ""));
            }
            
            ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(updateTag.getName_tag());
                
            List<Mutation> mutations = new ArrayList<Mutation>();

            ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
            Mutation m = new Mutation();
            
            colorsupcol.setSuper_column(liststatus);
            m.setColumn_or_supercolumn(colorsupcol);
            mutations.add(m);

            Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
            keyMutations.put(Tag.col_parent, mutations);

            Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
            mutationsMap.put(rowkey, keyMutations);
            client.batch_mutate(mutationsMap, common.Constants.CL);
                   
            result = true;
           
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return result;
        
    }
    
    public Tag selectTagFromID(String nameTag)
    {
        Tag result = new Tag();
        
        try {
        
            SlicePredicate predicate = new SlicePredicate();
            SliceRange range = new SliceRange(GeneralHandling.toByteBuffer(""), GeneralHandling.toByteBuffer(""), false, 10);
            predicate.setSlice_range(range);

            ColumnParent parent = new ColumnParent(Tag.col_parent);

            List<ColumnOrSuperColumn> results = client.get_slice(GeneralHandling.toByteBuffer(nameTag), parent, predicate, common.Constants.CL);

            if (!results.isEmpty())
            {
                result.setName_tag(nameTag);
                for (ColumnOrSuperColumn temp : results)
                {
                    SuperColumn sc = temp.super_column;
                    String colname = common.GeneralHandling.toString(sc.name);
                    if (Tag.name_scol_lstatus.equals(colname))
                    {
                        List<String> list_status_ID = new ArrayList<String>();
                        for (Column col : sc.columns)
                            list_status_ID.add(common.GeneralHandling.toString(col.name));
                        result.setList_status_ID(list_status_ID);
                    }
                    else
                        for (Column col : sc.columns)
                        {
                            String name = common.GeneralHandling.toString(col.name);
                            switch (name.charAt(0))
                            {
                                case 'c':
                                {
                                    result.setCreate_date(common.GeneralHandling.toString(col.value));
                                }
                                case 'm':
                                {
                                    result.setModify_date(common.GeneralHandling.toString(col.value));
                                }
                                case 's':
                                {
                                    result.setState("public");
                                }
                            }
                        }
                    }
                }
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
    
    public boolean RemoveTag(String rowkey)
    {
        boolean result = false;
        try {
            
            long time = System.currentTimeMillis();
            ColumnPath path = new ColumnPath();
            path.column_family = Tag.col_parent;
            path.super_column = common.GeneralHandling.toByteBuffer(Tag.name_scol_info); 
            client.remove(common.GeneralHandling.toByteBuffer(rowkey),path,time,common.Constants.CL);
            
            path = new ColumnPath();
            path.column_family = Tag.col_parent;
            path.super_column = common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus); 
            client.remove(common.GeneralHandling.toByteBuffer(rowkey),path,time,common.Constants.CL);
            
            result = true;
            
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return result;
    }
    
    public void PrintALLTag()
    {
        try {
            List<ByteBuffer> colNames = new ArrayList<ByteBuffer>();
            colNames.add(common.GeneralHandling.toByteBuffer(Tag.name_scol_info));
            SlicePredicate predicate = new SlicePredicate();
            predicate.column_names = colNames;
            
            ColumnParent parent = new ColumnParent(Tag.col_parent); 
            KeyRange range = new KeyRange();
            range.start_key = common.GeneralHandling.toByteBuffer("");
            range.end_key = common.GeneralHandling.toByteBuffer("");
            
            List<KeySlice> results = client.get_range_slices(parent, predicate, range, common.Constants.CL);
            for (KeySlice row : results)
            {
                Tag temp = selectTagFromID(common.GeneralHandling.toString(row.key));
                if (temp.getName_tag() != null)
                    PrintTag(temp);
            }
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
    private void PrintTag(Tag temp)
    {
        System.out.println("Key : " + temp.getName_tag());
        System.out.println("List status ID : ");
        List<String> list = temp.getList_status_ID();
        for (int i = 0; i < list.size(); i++)
        {
            String x = list.get(i) + ", ";
            System.out.print(x);
        }
        System.out.println();
        System.out.println("Create Date : " + temp.getCreate_date());
        System.out.println("Modify Date : " + temp.getModify_date());
        System.out.println("State : " + temp.getState());
        System.out.println("-----------------------------------------");
    }
    
    public String PrintALLTag_S()
    {
        String result = "{\"result\":[";
        try {
            List<ByteBuffer> colNames = new ArrayList<ByteBuffer>();
            colNames.add(common.GeneralHandling.toByteBuffer(Tag.name_scol_info));
            SlicePredicate predicate = new SlicePredicate();
            predicate.column_names = colNames;
            
            ColumnParent parent = new ColumnParent(Tag.col_parent); 
            KeyRange range = new KeyRange();
            range.start_key = common.GeneralHandling.toByteBuffer("");
            range.end_key = common.GeneralHandling.toByteBuffer("");
            
            List<KeySlice> results = client.get_range_slices(parent, predicate, range, common.Constants.CL);
            for (KeySlice row : results)
            {
                Tag temp = selectTagFromID(common.GeneralHandling.toString(row.key));
                if (temp.getName_tag() != null && temp.getList_status_ID() != null)
                    result += PrintTag_S(temp);
            }
            result = result.substring(0, result.length()-1);
            result += "]}";
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
    
    private String PrintTag_S(Tag temp)
    {
        String result = "";
        result += "{\"Key\":\"" + temp.getName_tag() + "\",";
        result += "\"List status ID\":\"";
        List<String> list = temp.getList_status_ID();
        for (int i = 0; i < list.size(); i++)
        {
            String x = list.get(i) + ",";
            result += x;
        }
        result = result.substring(0, result.length()-1);
        result += "\",";
        result += "\"Create Date\":\"" + temp.getCreate_date() + "\",";
        result += "\"Modify Date\":\"" + temp.getModify_date() + "\",";
        result += "\"State\":\"" + temp.getState() + "\"},";
        return result;
    }
}
